<?php
/**
 * 容器类
 * 
 * Copyright (c) 2014~2019 https://desion.net All rights reserved.
 * Author: 阿林 QQ:120867629 <linhong00@gmail.com>
 */
declare (strict_types = 1);
namespace dsphp;
use InvalidArgumentException;
use IteratorAggregate;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;

class Container
{
    // 容器中的对象实例
    private static $instances = [];
    // 容器绑定标识
    private static $binds = [];


    public static function init(array $bind = [])
    {
        self::$binds     = $bind;
        self::$instances = [];
    }

    /**
     * 返回当前实例集
     *
     * @return void
     */
    public static function instances():array
    {
        return self::$instances;
    }

    /**
     * 绑定一个类、接口实现到容器
     * 
     * @param string  $abstract 类标识、接口
     * @param string  $concrete 要绑定的类
     * @return $this
     */
    public static function bind(string $abstract, string $concrete)
    {
        self::$binds[$abstract] = $concrete;
    }

    /**
     * 绑定一个类实例到容器
     *
     * @param string $abstract 类名或者标识
     * @param object $instance 类的实例
     * @return $this
     */
    public static function instance(string $abstract, object $instance)
    {
        if (isset(self::$binds[$abstract])) {
            $bind = self::$binds[$abstract];

            if (is_string($bind)) {
                return self::instance($bind, $instance);
            }   
        }

        self::$instances[$abstract] = $instance;
    }

    /**
     * 判断容器中是否存在类及标识
     *
     * @param string $abstract 类名或者标识
     */
    public static function bound(string $abstract): bool
    {
        return isset(self::$binds[$abstract]) || isset(self::$instances[$abstract]);
    }

    /**
     * 判断容器中是否存在类及标识
     *
     * @param string $name 类名或者标识
     */
    public static function has($name): bool
    {
        return self::bound($name);
    }

    /**
     * 判断容器中是否存在对象实例
     *
     * @param string $abstract 类名或者标识 
     * @param bool   $return   是否返回类
     */
    public static function exists(string $abstract, bool $return = false)
    {
        $abstract = self::getBindName($abstract);
        $status   = isset(self::$instances[$abstract]);

        if ($return && $status) {
            return self::$instances[$abstract];
        }

        return $status;
    }

    /**
     * 删除容器中的对象实例
     *
     * @param string $name 类名或者标识
     * @return void
     */
    public static function delete($name)
    {
        $name = self::getBindName($name);

        if (isset(self::$instances[$name])) {
            unset(self::$instances[$name]);
        }
    }

    /**
     * 获取绑定名称。无绑定直接返回
     *
     * @param string $abstract    标识
     */
    public static function getBindName(string $abstract):string
    {
        if (isset(self::$binds[$abstract])) {
            $bind = self::$binds[$abstract];

            if (is_string($bind)) {
                $abstract = $bind;
            }
        }

        return $abstract;
    }
}
